// This work is licensed under a Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0) https://creativecommons.org/licenses/by-nc-sa/4.0/
// © LuxAlgo

//@version=5
indicator("HTF Candle Consistency [LuxAlgo]", "LuxAlgo - HTF Candle Consistency", overlay = true)

//---------------------------------------------------------------------------------------------------------------------}
//User Inputs
//---------------------------------------------------------------------------------------------------------------------{
group1 = "Toggle       Timeframe                    Weight"

tf1Tog = input.bool(true, title = "", group = group1, inline = "1")
tf1 = input.timeframe("5", title = "", group = group1, inline = "1")
tf1Multi = input.float(1, title = "", step = 0.1, group = group1, inline = "1")

tf2Tog = input.bool(true, title = "", group = group1, inline = "2")
tf2 = input.timeframe("10", title = "", group = group1, inline = "2")
tf2Multi = input.float(1, title = "", step = 0.1, group = group1, inline = "2")

tf3Tog = input.bool(true, title = "", group = group1, inline = "3")
tf3 = input.timeframe("15", title = "", group = group1, inline = "3")
tf3Multi = input.float(1, title = "", step = 0.1, group = group1, inline = "3")

tf4Tog = input.bool(true, title = "", group = group1, inline = "4")
tf4 = input.timeframe("30", title = "", group = group1, inline = "4")
tf4Multi = input.float(1, title = "", step = 0.1, group = group1, inline = "4")

tf5Tog = input.bool(true, title = "", group = group1, inline = "5")
tf5 = input.timeframe("60", title = "", group = group1, inline = "5")
tf5Multi = input.float(1, title = "", step = 0.1, group = group1, inline = "5")

tf6Tog = input.bool(true, title = "", group = group1, inline = "6")
tf6 = input.timeframe("120", title = "", group = group1, inline = "6")
tf6Multi = input.float(1, title = "", step = 0.1, group = group1, inline = "6")

tf7Tog = input.bool(true, title = "", group = group1, inline = "7")
tf7 = input.timeframe("240", title = "", group = group1, inline = "7")
tf7Multi = input.float(1, title = "", step = 0.1, group = group1, inline = "7")

tf8Tog = input.bool(true, title = "", group = group1, inline = "8")
tf8 = input.timeframe("D", title = "", group = group1, inline = "8")
tf8Multi = input.float(1, title = "", step = 0.1, group = group1, inline = "8")

tf9Tog = input.bool(true, title = "", group = group1, inline = "9")
tf9 = input.timeframe("W", title = "", group = group1, inline = "9")
tf9Multi = input.float(1, title = "", step = 0.1, group = group1, inline = "9")

tf10Tog = input.bool(true, title = "", group = group1, inline = "10")
tf10 = input.timeframe("M", title = "", group = group1, inline = "10")
tf10Multi = input.float(1, title = "", step = 0.1, group = group1, inline = "10")

colorMode = input.string("Tricolor", "Color Mode", options = ["Bicolor", "Tricolor", "Gradient"], group = "Style")
green = input.color(#089981, title = "Bullish Color", group = "Style")
silver = input.color(color.silver, title = "Neutral Color", group = "Style")
red = input.color(#f23645, title = "Bearish Color", group = "Style")

showDash = input.bool(true,title = "Show Dashboard", group = "Dashboard")
dashLoc  = str.lower(str.replace_all(input.string("Top Right",title =  "Location", options = ["Top Right", "Bottom Right", "Bottom Left"] , group = "Dashboard")," ","_"))
textSize = str.lower(input.string("Small", title = "Size", options = ["Tiny", "Small", "Normal"], group = "Dashboard"))
vert = input.string("Vertical", title = "Orientation", group = "Dashboard", options = ["Vertical", "Horizontal"]) == "Vertical"

//---------------------------------------------------------------------------------------------------------------------}
//Functions
//---------------------------------------------------------------------------------------------------------------------{

//Grabs HTF open and compares it to current close to determine if it moved up or down
get_htf_dir(_tog,_tf) =>
    o = request.security("", _tf, open, lookahead = barmerge.lookahead_on) //Lookahead on with no offset provides the current HTF bar's OPEN value.
    dir = (close > o) ? 1 : (close < o) ? -1 : 0                           //Since this value is determined on the Opening of the bar, for the rest of the bar is essentially historical.
    (_tog?dir:0)                                                           //For this reason (and the need for the current Bar's ACTUAL open price) we have chosen to use it here.

//3 Colored Gradient - Includes a middle transition color
tri_grad(_val,_bot_val,_top_val,_bot_col, _mid_col, _top_col) =>
    mid = math.avg(_bot_val,_top_val)
    color1 = color.from_gradient(_val,_bot_val,mid,_bot_col,_mid_col)
    color2 = color.from_gradient(_val,mid,_top_val,_mid_col,_top_col)
    (_val>mid?color2:color1)

//For table colors
get_col(_val) => _val > 0? green : _val < 0 ? red : color.gray

//For text color, if the requested timeframe is below the current timeframe we want to let the user know about it.
//This function changes the text color to red
check_tf(_tf) => timeframe.in_seconds(_tf) < timeframe.in_seconds(timeframe.period) ? color.red : color.white
//This function changes the tooltip
check_tf_tt(_tf) => timeframe.in_seconds(_tf) < timeframe.in_seconds(timeframe.period) ?
  "The Requested Timeframe should be Equal-to or Higher than the Current Chart Timeframe.\nThis information should be considered inaccurate for analysis.\nIt is recommended that you change or disable this timeframe.": 
  na

//---------------------------------------------------------------------------------------------------------------------}
//Calculations
//---------------------------------------------------------------------------------------------------------------------{

data = array.new_float(na)

//Getting directions and multiplying by multipliers for weighting
val1 = get_htf_dir(tf1Tog,tf1)*tf1Multi
val2 = get_htf_dir(tf2Tog,tf2)*tf2Multi
val3 = get_htf_dir(tf3Tog,tf3)*tf3Multi
val4 = get_htf_dir(tf4Tog,tf4)*tf4Multi
val5 = get_htf_dir(tf5Tog,tf5)*tf5Multi
val6 = get_htf_dir(tf6Tog,tf6)*tf6Multi
val7 = get_htf_dir(tf7Tog,tf7)*tf7Multi
val8 = get_htf_dir(tf8Tog,tf8)*tf8Multi
val9 = get_htf_dir(tf9Tog,tf9)*tf9Multi
val10 = get_htf_dir(tf10Tog,tf10)*tf10Multi

//Sending data to array
data.push(val1)
data.push(val2)
data.push(val3)
data.push(val4)
data.push(val5)
data.push(val6)
data.push(val7)
data.push(val8)
data.push(val9)
data.push(val10)

//The max and min possible within the data are the total of all weights.
weight_sum = 
  (tf1Tog?tf1Multi:0) + 
  (tf2Tog?tf2Multi:0) + 
  (tf3Tog?tf3Multi:0) + 
  (tf4Tog?tf4Multi:0) + 
  (tf5Tog?tf5Multi:0) + 
  (tf6Tog?tf6Multi:0) + 
  (tf7Tog?tf7Multi:0) + 
  (tf8Tog?tf8Multi:0) + 
  (tf9Tog?tf9Multi:0) + 
  (tf10Tog?tf10Multi:0)

//---------------------------------------------------------------------------------------------------------------------}
//Candle Colors
//---------------------------------------------------------------------------------------------------------------------{

can_color = switch colorMode
    "Bicolor" => data.sum() > 0 ? green : red
    "Tricolor" => data.sum() > weight_sum / 3 ? green : data.sum() < -weight_sum / 3 ? red : silver
    "Gradient" => tri_grad(data.sum(), -weight_sum, weight_sum, red, silver, green) 

barcolor(can_color)

//---------------------------------------------------------------------------------------------------------------------}
//Table
//---------------------------------------------------------------------------------------------------------------------{

//Table setup
var tb = table.new(dashLoc, 10, 10
  , bgcolor      = #1e222d
  , border_color = #373a46
  , border_width = 1
  , frame_color  = #373a46
  , frame_width  = 1) 

//Getting the widths for each display style
vert_width = textSize == "normal" ? 0.5 : 0.25
flat_width = textSize == "normal" ? 2 : 1

//Sending everything to the table
if showDash
    if tf1Tog
        tb.cell((vert?0:0),(vert?0:1), tf1,text_color = check_tf(tf1), text_size = textSize, tooltip = check_tf_tt(tf1))
        tb.cell((vert?1:0),(vert?0:0), bgcolor = get_col(val1), height = 1, width = (vert?vert_width:flat_width))

    if tf2Tog
        tb.cell((vert?0:1),(vert?1:1), tf2,text_color = check_tf(tf2), text_size = textSize, tooltip = check_tf_tt(tf2))
        tb.cell((vert?1:1),(vert?1:0), bgcolor = get_col(val2), height = 1, width = (vert?vert_width:flat_width))

    if tf3Tog
        tb.cell((vert?0:2),(vert?2:1), tf3,text_color = check_tf(tf3), text_size = textSize, tooltip = check_tf_tt(tf3))
        tb.cell((vert?1:2),(vert?2:0), bgcolor = get_col(val3), height = 1, width = (vert?vert_width:flat_width))

    if tf4Tog
        tb.cell((vert?0:3),(vert?3:1), tf4,text_color = check_tf(tf4), text_size = textSize, tooltip = check_tf_tt(tf4))
        tb.cell((vert?1:3),(vert?3:0), bgcolor = get_col(val4), height = 1, width = (vert?vert_width:flat_width))

    if tf5Tog
        tb.cell((vert?0:4),(vert?4:1), tf5,text_color = check_tf(tf5), text_size = textSize, tooltip = check_tf_tt(tf5))
        tb.cell((vert?1:4),(vert?4:0), bgcolor = get_col(val5), height = 1, width = (vert?vert_width:flat_width))

    if tf6Tog
        tb.cell((vert?0:5),(vert?5:1), tf6,text_color = check_tf(tf6), text_size = textSize, tooltip = check_tf_tt(tf6))
        tb.cell((vert?1:5),(vert?5:0), bgcolor = get_col(val6), height = 1, width = (vert?vert_width:flat_width))

    if tf7Tog
        tb.cell((vert?0:6),(vert?6:1), tf7,text_color = check_tf(tf7), text_size = textSize, tooltip = check_tf_tt(tf7))
        tb.cell((vert?1:6),(vert?6:0), bgcolor = get_col(val7), height = 1, width = (vert?vert_width:flat_width))

    if tf8Tog
        tb.cell((vert?0:7),(vert?7:1), tf8,text_color = check_tf(tf8), text_size = textSize, tooltip = check_tf_tt(tf8))
        tb.cell((vert?1:7),(vert?7:0), bgcolor = get_col(val8), height = 1, width = (vert?vert_width:flat_width))

    if tf9Tog
        tb.cell((vert?0:8),(vert?8:1), tf9,text_color = check_tf(tf9), text_size = textSize, tooltip = check_tf_tt(tf9))
        tb.cell((vert?1:8),(vert?8:0), bgcolor = get_col(val9), height = 1, width = (vert?vert_width:flat_width))

    if tf10Tog
        tb.cell((vert?0:9),(vert?9:1), tf10,text_color = check_tf(tf10), text_size = textSize, tooltip = check_tf_tt(tf10))
        tb.cell((vert?1:9),(vert?9:0), bgcolor = get_col(val10), height = 1, width = (vert?vert_width:flat_width))

//---------------------------------------------------------------------------------------------------------------------}